/**
* Copyright (c) 2006-2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
*/
package org.eclipse.emf.test.core.ecore;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EEnumLiteral;
import org.eclipse.emf.ecore.EGenericType;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EParameter;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.ETypeParameter;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.util.Diagnostician;
import org.eclipse.emf.ecore.util.EObjectValidator;
import org.eclipse.emf.ecore.util.EcoreValidator;
import org.eclipse.emf.ecore.xml.type.XMLTypePackage;
import org.junit.Before;
import org.junit.Test;
public class EcoreValidationTest
{
protected static final boolean SYSOUT = false;
@Before
public void setUp()
{
EcorePackage.eINSTANCE.eClass();
}
@Test
public void testEcoreValidator()
{
// Validate that the Ecore package instance itself is okay.
{
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(EcorePackage.eINSTANCE);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
}
// An annotation with an empty string for the source isn't valid.
{
EAnnotation eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation();
eAnnotation.setSource("");
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eAnnotation);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.WELL_FORMED_SOURCE_URI,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eAnnotation, EcorePackage.Literals.EANNOTATION__SOURCE },
diagnostic.getChildren().get(0));
}
// An annotation with a source containing a space isn't valid.
{
EAnnotation eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation();
eAnnotation.setSource("a b");
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eAnnotation);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.WELL_FORMED_SOURCE_URI,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eAnnotation, EcorePackage.Literals.EANNOTATION__SOURCE },
diagnostic.getChildren().get(0));
}
// Two map entries with the same key are not valid.
//
{
EAnnotation eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation();
{
EObject entry = EcoreFactory.eINSTANCE.create(EcorePackage.Literals.ESTRING_TO_STRING_MAP_ENTRY);
entry.eSet(EcorePackage.Literals.ESTRING_TO_STRING_MAP_ENTRY__KEY, "a");
@SuppressWarnings("unchecked")
Map.Entry<String, String> stringToStringMapEntry = (Map.Entry<String, String>)entry;
eAnnotation.getDetails().add(stringToStringMapEntry);
}
{
EObject entry = EcoreFactory.eINSTANCE.create(EcorePackage.Literals.ESTRING_TO_STRING_MAP_ENTRY);
entry.eSet(EcorePackage.Literals.ESTRING_TO_STRING_MAP_ENTRY__KEY, "a");
@SuppressWarnings("unchecked")
Map.Entry<String, String> stringToStringMapEntry = (Map.Entry<String, String>)entry;
eAnnotation.getDetails().add(stringToStringMapEntry);
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eAnnotation);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EObjectValidator.EOBJECT__EVERY_MAP_ENTRY_UNIQUE,
EObjectValidator.DIAGNOSTIC_SOURCE,
new Object [] { eAnnotation, EcorePackage.Literals.EANNOTATION__DETAILS, eAnnotation.getDetails().get(1), eAnnotation.getDetails().get(0) },
diagnostic.getChildren().get(0));
}
// A named element without a name is invalid, unless strict element names are disabled.
//
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eClass);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.WELL_FORMED_NAME,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eClass, EcorePackage.Literals.ENAMED_ELEMENT__NAME },
diagnostic.getChildren().get(0));
diagnostic = Diagnostician.INSTANCE.validate(eClass, Collections.singletonMap(EcoreValidator.STRICT_NAMED_ELEMENT_NAMES, Boolean.FALSE));
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
}
// An instance type name with type arguments is valid.
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("_");
eClass.setInstanceTypeName("_<_>");
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eClass);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
}
// An instance type name that's just an empty string is not valid.
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("_");
eClass.setInstanceTypeName("");
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eClass);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.WELL_FORMED_INSTANCE_TYPE_NAME,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eClass, EcorePackage.Literals.ECLASSIFIER__INSTANCE_TYPE_NAME },
diagnostic.getChildren().get(0));
}
// An instance type name with unbalanced "<" is not valid.
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("_");
eClass.setInstanceTypeName("_<_");
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eClass);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.WELL_FORMED_INSTANCE_TYPE_NAME,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eClass, EcorePackage.Literals.ECLASSIFIER__INSTANCE_TYPE_NAME },
diagnostic.getChildren().get(0));
}
// An instance type name with unbalanced "[" is not valid.
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("_");
eClass.setInstanceTypeName("_[");
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eClass);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.WELL_FORMED_INSTANCE_TYPE_NAME,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eClass, EcorePackage.Literals.ECLASSIFIER__INSTANCE_TYPE_NAME },
diagnostic.getChildren().get(0));
}
// A class that is an interface must also be abstract.
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("_");
eClass.setInterface(true);
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eClass);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.INTERFACE_IS_ABSTRACT,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eClass, EcorePackage.Literals.ECLASS__ABSTRACT },
diagnostic.getChildren().get(0));
}
// A class can't have more than one attribute that is an ID.
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("_");
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName("a");
eAttribute.setID(true);
eAttribute.setEType(EcorePackage.Literals.ESTRING);
eClass.getEStructuralFeatures().add(eAttribute);
}
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName("b");
eAttribute.setID(true);
eAttribute.setEType(EcorePackage.Literals.ESTRING);
eClass.getEStructuralFeatures().add(eAttribute);
}
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName("c");
eAttribute.setID(true);
eAttribute.setEType(EcorePackage.Literals.ESTRING);
eClass.getEStructuralFeatures().add(eAttribute);
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eClass);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.AT_MOST_ONE_ID,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eClass, eClass.getEAttributes().get(0), eClass.getEAttributes().get(1), eClass.getEAllAttributes().get(2), EcorePackage.Literals.ECLASS__EALL_ATTRIBUTES},
diagnostic.getChildren().get(0));
}
// A class can't have two attributes with the same name.
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("_");
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName("a");
eAttribute.setEType(EcorePackage.Literals.ESTRING);
eClass.getEStructuralFeatures().add(eAttribute);
}
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName("a");
eAttribute.setEType(EcorePackage.Literals.ESTRING);
eClass.getEStructuralFeatures().add(eAttribute);
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eClass);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.UNIQUE_FEATURE_NAMES,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eClass, eClass.getEAttributes().get(0), eClass.getEAttributes().get(1), EcorePackage.Literals.ECLASS__EALL_STRUCTURAL_FEATURES },
diagnostic.getChildren().get(0));
}
// A class can't have two attributes with the matching names.
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("_");
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName("a");
eAttribute.setEType(EcorePackage.Literals.ESTRING);
eClass.getEStructuralFeatures().add(eAttribute);
}
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName("A_");
eAttribute.setEType(EcorePackage.Literals.ESTRING);
eClass.getEStructuralFeatures().add(eAttribute);
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eClass);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.WARNING,
EcoreValidator.UNIQUE_FEATURE_NAMES,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eClass, eClass.getEAttributes().get(0), eClass.getEAttributes().get(1), EcorePackage.Literals.ECLASS__EALL_STRUCTURAL_FEATURES },
diagnostic.getChildren().get(0));
}
// A class can't have two operations with matching signatures.
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("_");
{
EOperation eOperation = EcoreFactory.eINSTANCE.createEOperation();
eOperation.setName("a");
{
EParameter eParameter = EcoreFactory.eINSTANCE.createEParameter();
eParameter.setName("x");
eParameter.setEType(XMLTypePackage.Literals.HEX_BINARY);
eOperation.getEParameters().add(eParameter);
}
eClass.getEOperations().add(eOperation);
}
{
EOperation eOperation = EcoreFactory.eINSTANCE.createEOperation();
eOperation.setName("a");
{
EParameter eParameter = EcoreFactory.eINSTANCE.createEParameter();
eParameter.setName("x");
eParameter.setEType(XMLTypePackage.Literals.BASE64_BINARY);
eOperation.getEParameters().add(eParameter);
}
eClass.getEOperations().add(eOperation);
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eClass);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.UNIQUE_OPERATION_SIGNATURES,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eClass, eClass.getEOperations().get(0), eClass.getEOperations().get(1), EcorePackage.Literals.ECLASS__EALL_OPERATIONS },
diagnostic.getChildren().get(0));
}
// A class can't have circular super types.
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.getESuperTypes().add(eClass);
eClass.setName("_");
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eClass);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.NO_CIRCULAR_SUPER_TYPES,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eClass, EcorePackage.Literals.ECLASS__EALL_SUPER_TYPES },
diagnostic.getChildren().get(0));
}
// A map entry class must have a key feature and a value feature.
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("_");
eClass.setInstanceClassName("java.util.Map$Entry");
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eClass);
assertEquals(2, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.WELL_FORMED_MAP_ENTRY_CLASS,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eClass, EcorePackage.Literals.ECLASS__EALL_STRUCTURAL_FEATURES },
diagnostic.getChildren().get(0));
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.WELL_FORMED_MAP_ENTRY_CLASS,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eClass, EcorePackage.Literals.ECLASS__EALL_STRUCTURAL_FEATURES },
diagnostic.getChildren().get(1));
}
// Two enum literals can't have the same name nor matching names.
{
EEnum eEnum = EcoreFactory.eINSTANCE.createEEnum();
eEnum.setName("_");
{
EEnumLiteral eEnumLiteral = EcoreFactory.eINSTANCE.createEEnumLiteral();
eEnumLiteral.setName("a");
eEnum.getELiterals().add(eEnumLiteral);
}
{
EEnumLiteral eEnumLiteral = EcoreFactory.eINSTANCE.createEEnumLiteral();
eEnumLiteral.setName("a");
eEnum.getELiterals().add(eEnumLiteral);
}
{
EEnumLiteral eEnumLiteral = EcoreFactory.eINSTANCE.createEEnumLiteral();
eEnumLiteral.setName("A");
eEnum.getELiterals().add(eEnumLiteral);
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eEnum);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.UNIQUE_ENUMERATOR_NAMES,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eEnum, eEnum.getELiterals().get(0), eEnum.getELiterals().get(1), eEnum.getELiterals().get(2), EcorePackage.Literals.EENUM__ELITERALS },
diagnostic.getChildren().get(0));
}
// Two enum literals can't have the same literals.
{
EEnum eEnum = EcoreFactory.eINSTANCE.createEEnum();
eEnum.setName("_");
{
EEnumLiteral eEnumLiteral = EcoreFactory.eINSTANCE.createEEnumLiteral();
eEnumLiteral.setName("a");
eEnumLiteral.setLiteral("x");
eEnum.getELiterals().add(eEnumLiteral);
}
{
EEnumLiteral eEnumLiteral = EcoreFactory.eINSTANCE.createEEnumLiteral();
eEnumLiteral.setName("b");
eEnumLiteral.setLiteral("x");
eEnum.getELiterals().add(eEnumLiteral);
}
{
EEnumLiteral eEnumLiteral = EcoreFactory.eINSTANCE.createEEnumLiteral();
eEnumLiteral.setName("c");
eEnumLiteral.setLiteral("x");
eEnum.getELiterals().add(eEnumLiteral);
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eEnum);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.UNIQUE_ENUMERATOR_LITERALS,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eEnum, eEnum.getELiterals().get(0), eEnum.getELiterals().get(1), eEnum.getELiterals().get(2), EcorePackage.Literals.EENUM__ELITERALS },
diagnostic.getChildren().get(0));
}
// Two parameters cannot have the same name.
{
EOperation eOperation = EcoreFactory.eINSTANCE.createEOperation();
eOperation.setName("_");
{
EParameter eParameter = EcoreFactory.eINSTANCE.createEParameter();
eParameter.setName("a");
eParameter.setEType(EcorePackage.Literals.ESTRING);
eOperation.getEParameters().add(eParameter);
}
{
EParameter eParameter = EcoreFactory.eINSTANCE.createEParameter();
eParameter.setName("a");
eParameter.setEType(EcorePackage.Literals.ESTRING);
eOperation.getEParameters().add(eParameter);
}
{
EParameter eParameter = EcoreFactory.eINSTANCE.createEParameter();
eParameter.setName("a");
eParameter.setEType(EcorePackage.Literals.ESTRING);
eOperation.getEParameters().add(eParameter);
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eOperation);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.UNIQUE_PARAMETER_NAMES,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eOperation, eOperation.getEParameters().get(0), eOperation.getEParameters().get(1), eOperation.getEParameters().get(2), EcorePackage.Literals.EOPERATION__EPARAMETERS },
diagnostic.getChildren().get(0));
}
// Two type parameters cannot have the same name.
{
EOperation eOperation = EcoreFactory.eINSTANCE.createEOperation();
eOperation.setName("_");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("A");
eOperation.getETypeParameters().add(eTypeParameter);
}
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("A");
eOperation.getETypeParameters().add(eTypeParameter);
}
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("A");
eOperation.getETypeParameters().add(eTypeParameter);
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eOperation);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.UNIQUE_TYPE_PARAMETER_NAMES,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eOperation, eOperation.getETypeParameters().get(0), eOperation.getETypeParameters().get(1), eOperation.getETypeParameters().get(2), EcorePackage.Literals.EOPERATION__ETYPE_PARAMETERS },
diagnostic.getChildren().get(0));
}
// Two type parameters cannot have the same name.
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("_");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("A");
eClass.getETypeParameters().add(eTypeParameter);
}
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("A");
eClass.getETypeParameters().add(eTypeParameter);
}
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("A");
eClass.getETypeParameters().add(eTypeParameter);
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eClass);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.UNIQUE_TYPE_PARAMETER_NAMES,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eClass, eClass.getETypeParameters().get(0), eClass.getETypeParameters().get(1), eClass.getETypeParameters().get(2), EcorePackage.Literals.ECLASSIFIER__ETYPE_PARAMETERS },
diagnostic.getChildren().get(0));
}
// A void operation must have upper bound 1.
{
EOperation eOperation = EcoreFactory.eINSTANCE.createEOperation();
eOperation.setName("_");
eOperation.setUpperBound(2);
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eOperation);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.NO_REPEATING_VOID,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eOperation, EcorePackage.Literals.ETYPED_ELEMENT__UPPER_BOUND },
diagnostic.getChildren().get(0));
}
// A package must have an nsURI.
{
EPackage ePackage = EcoreFactory.eINSTANCE.createEPackage();
ePackage.setName("_");
ePackage.setNsPrefix("");
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.WELL_FORMED_NS_URI,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { ePackage, EcorePackage.Literals.EPACKAGE__NS_URI },
diagnostic.getChildren().get(0));
}
// A null string is not a well formed nsURI for a package.
{
EPackage ePackage = EcoreFactory.eINSTANCE.createEPackage();
ePackage.setName("_");
ePackage.setNsURI("");
ePackage.setNsPrefix("");
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.WELL_FORMED_NS_URI,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { ePackage, EcorePackage.Literals.EPACKAGE__NS_URI },
diagnostic.getChildren().get(0));
}
// A string with a space is not a well formed nsURI for a package.
{
EPackage ePackage = EcoreFactory.eINSTANCE.createEPackage();
ePackage.setName("_");
ePackage.setNsURI("a b");
ePackage.setNsPrefix("");
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.WELL_FORMED_NS_URI,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { ePackage, EcorePackage.Literals.EPACKAGE__NS_URI },
diagnostic.getChildren().get(0));
}
// A prefix that starts with "xml" is not a well formed nsPrefix for a package.
{
EPackage ePackage = EcoreFactory.eINSTANCE.createEPackage();
ePackage.setName("_");
ePackage.setNsURI("_");
ePackage.setNsPrefix("xml");
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.WELL_FORMED_NS_PREFIX,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { ePackage, EcorePackage.Literals.EPACKAGE__NS_PREFIX },
diagnostic.getChildren().get(0));
}
// A prefix that isn't an NCName because it contains a ":" is not a well formed nsPrefix for a package.
{
EPackage ePackage = EcoreFactory.eINSTANCE.createEPackage();
ePackage.setName("_");
ePackage.setNsURI("_");
ePackage.setNsPrefix("a:b");
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.WELL_FORMED_NS_PREFIX,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { ePackage, EcorePackage.Literals.EPACKAGE__NS_PREFIX },
diagnostic.getChildren().get(0));
}
// A null prefix that an NCName and is not a well formed nsPrefix for a package.
{
EPackage ePackage = EcoreFactory.eINSTANCE.createEPackage();
ePackage.setName("_");
ePackage.setNsURI("_");
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.WELL_FORMED_NS_PREFIX,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { ePackage, EcorePackage.Literals.EPACKAGE__NS_PREFIX },
diagnostic.getChildren().get(0));
}
// Two subpackages cannot have the same name.
{
EPackage ePackage = EcoreFactory.eINSTANCE.createEPackage();
ePackage.setName("_");
ePackage.setNsURI("_");
ePackage.setNsPrefix("");
{
EPackage eSubpackage = EcoreFactory.eINSTANCE.createEPackage();
eSubpackage.setName("a");
eSubpackage.setNsURI("a");
eSubpackage.setNsPrefix("");
ePackage.getESubpackages().add(eSubpackage);
}
{
EPackage eSubpackage = EcoreFactory.eINSTANCE.createEPackage();
eSubpackage.setName("a");
eSubpackage.setNsURI("b");
eSubpackage.setNsPrefix("");
ePackage.getESubpackages().add(eSubpackage);
}
{
EPackage eSubpackage = EcoreFactory.eINSTANCE.createEPackage();
eSubpackage.setName("a");
eSubpackage.setNsURI("c");
eSubpackage.setNsPrefix("");
ePackage.getESubpackages().add(eSubpackage);
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.UNIQUE_SUBPACKAGE_NAMES,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { ePackage, ePackage.getESubpackages().get(0), ePackage.getESubpackages().get(1), ePackage.getESubpackages().get(2), EcorePackage.Literals.EPACKAGE__ESUBPACKAGES },
diagnostic.getChildren().get(0));
}
// Two classifiers cannot have the same name nor matching names.
{
EPackage ePackage = EcoreFactory.eINSTANCE.createEPackage();
ePackage.setName("_");
ePackage.setNsURI("_");
ePackage.setNsPrefix("");
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("a");
ePackage.getEClassifiers().add(eClass);
}
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("a");
ePackage.getEClassifiers().add(eClass);
}
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("A");
ePackage.getEClassifiers().add(eClass);
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.UNIQUE_CLASSIFIER_NAMES,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { ePackage, ePackage.getEClassifiers().get(0), ePackage.getEClassifiers().get(1), ePackage.getEClassifiers().get(2), EcorePackage.Literals.EPACKAGE__ECLASSIFIERS },
diagnostic.getChildren().get(0));
}
// Two packages cannot have the same namespace URI.
{
EPackage ePackage = EcoreFactory.eINSTANCE.createEPackage();
ePackage.setName("_");
ePackage.setNsURI("_");
ePackage.setNsPrefix("");
{
EPackage eSubpackage = EcoreFactory.eINSTANCE.createEPackage();
eSubpackage.setName("a");
eSubpackage.setNsURI("_");
eSubpackage.setNsPrefix("");
ePackage.getESubpackages().add(eSubpackage);
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(2, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.UNIQUE_NS_URIS,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { ePackage, ePackage.getESubpackages().get(0), EcorePackage.Literals.EPACKAGE__ESUBPACKAGES },
diagnostic.getChildren().get(0));
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.UNIQUE_NS_URIS,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { ePackage.getESubpackages().get(0), ePackage, EcorePackage.Literals.EPACKAGE__ESUBPACKAGES },
diagnostic.getChildren().get(1));
}
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName("_");
eAttribute.setEType(EcorePackage.Literals.ERESOURCE);
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eAttribute);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_TRANSIENT,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eAttribute, EcorePackage.Literals.ESTRUCTURAL_FEATURE__TRANSIENT },
diagnostic.getChildren().get(0));
}
// There are many ways for opposites to be inconsistent so we'll test them all.
LOOP:
for (int i = 0; i < 100; ++i)
{
EPackage ePackage = EcoreFactory.eINSTANCE.createEPackage();
EClass A;
EReference a;
EClass B;
EReference b;
ePackage.setName("_");
ePackage.setNsURI("_");
ePackage.setNsPrefix("");
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("A");
ePackage.getEClassifiers().add(eClass);
{
EReference eReference = EcoreFactory.eINSTANCE.createEReference();
eReference.setName("b");
eClass.getEStructuralFeatures().add(eReference);
b = eReference;
}
A = eClass;
}
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("B");
ePackage.getEClassifiers().add(eClass);
{
EReference eReference = EcoreFactory.eINSTANCE.createEReference();
eReference.setName("a");
eClass.getEStructuralFeatures().add(eReference);
a = eReference;
}
B = eClass;
}
switch (i)
{
// Valid unidirectional references.
case 0:
{
a.setEType(A);
b.setEType(B);
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
break;
}
// Valid bidirectional references.
case 1:
{
a.setEType(A);
a.setEOpposite(b);
b.setEType(B);
b.setEOpposite(a);
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
break;
}
// The opposite must be a feature of the reference's type.
case 2:
{
a.setEType(B); // <-- Bad type that doesn't have a b feature
a.setEOpposite(b);
b.setEType(B);
b.setEOpposite(a);
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_OPPOSITE_NOT_FROM_TYPE,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { a, b, B, EcorePackage.Literals.EREFERENCE__EOPPOSITE },
diagnostic.getChildren().get(0));
break;
}
// The opposite of the opposite must be the feature itself.
case 3:
{
a.setEType(A);
a.setEOpposite(b);
b.setEType(B);
// b.setEOpposite(a); <-- No opposite for the opposite
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_OPPOSITE_NOT_MATCHING,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { a, b, null, EcorePackage.Literals.EREFERENCE__EOPPOSITE },
diagnostic.getChildren().get(0));
break;
}
// Valid bidirectional container/containment references.
case 4:
{
a.setEType(A);
a.setEOpposite(b);
a.setContainment(true);
b.setEType(B);
b.setEOpposite(a);
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
break;
}
// A container reference must have upper bound 1.
case 5:
{
a.setEType(A);
a.setEOpposite(b);
a.setContainment(true);
b.setEType(B);
b.setEOpposite(a);
b.setUpperBound(2); // <-- Bad upper bound.
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.SINGLE_CONTAINER,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { b, EcorePackage.Literals.ETYPED_ELEMENT__UPPER_BOUND },
diagnostic.getChildren().get(0));
break;
}
// Valid bidirectional references that are transient at both ends.
case 6:
{
a.setEType(A);
a.setEOpposite(b);
a.setTransient(true);
b.setEType(B);
b.setEOpposite(a);
b.setTransient(true);
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
break;
}
// Valid bidirectional references with one transient end that doesn't resolve proxy.
case 7:
{
a.setEType(A);
a.setEOpposite(b);
a.setTransient(true);
b.setEType(B);
b.setEOpposite(a);
b.setResolveProxies(false);
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
break;
}
// Valid bidirectional references with on transient end that's a container.
case 8:
{
a.setEType(A);
a.setEOpposite(b);
a.setContainment(true);
b.setEType(B);
b.setEOpposite(a);
b.setTransient(true);
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
break;
}
// The opposite of a transient bidirectional reference must either be transient as, non-proxy resolving, or a container.
case 9:
{
a.setEType(A);
a.setEOpposite(b);
a.setTransient(true);
// a.setContainment(true); <-- Must be a containment for b to be a container and hence be valid.
b.setEType(B);
b.setEOpposite(a);
// b.setTransient(true); <-- Must be transient.
// b.setResolveProxies(false); <-- Or must not resolve proxies.
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_OPPOSITE_BAD_TRANSIENT,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { a, b, EcorePackage.Literals.EREFERENCE__EOPPOSITE, EcorePackage.Literals.ESTRUCTURAL_FEATURE__TRANSIENT },
diagnostic.getChildren().get(0));
break;
}
// Both sides can't be containment.
case 10:
{
a.setEType(A);
a.setEOpposite(b);
a.setContainment(true);
b.setEType(B);
b.setEOpposite(a);
b.setContainment(true);
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(2, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_OPPOSITE_BOTH_CONTAINMENT,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { b, a, EcorePackage.Literals.EREFERENCE__EOPPOSITE, EcorePackage.Literals.EREFERENCE__CONTAINMENT },
diagnostic.getChildren().get(0));
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_OPPOSITE_BOTH_CONTAINMENT,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { a, b, EcorePackage.Literals.EREFERENCE__EOPPOSITE, EcorePackage.Literals.EREFERENCE__CONTAINMENT },
diagnostic.getChildren().get(1));
break;
}
default:
{
break LOOP;
}
}
}
// The lower bound of a typed element must be >= 0.
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName("a");
eAttribute.setEType(EcorePackage.Literals.ESTRING);
eAttribute.setLowerBound(-1);
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eAttribute);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.VALID_LOWER_BOUND,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eAttribute, EcorePackage.Literals.ETYPED_ELEMENT__LOWER_BOUND },
diagnostic.getChildren().get(0));
}
// The upper bound of a typed elements must be -2, -1, or >= 1 not 3.
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName("a");
eAttribute.setEType(EcorePackage.Literals.ESTRING);
eAttribute.setUpperBound(-3);
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eAttribute);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.VALID_UPPER_BOUND,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eAttribute, EcorePackage.Literals.ETYPED_ELEMENT__UPPER_BOUND },
diagnostic.getChildren().get(0));
}
// The upper bound of a typed element cannot be 0.
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName("a");
eAttribute.setEType(EcorePackage.Literals.ESTRING);
eAttribute.setUpperBound(0);
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eAttribute);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.VALID_UPPER_BOUND,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eAttribute, EcorePackage.Literals.ETYPED_ELEMENT__UPPER_BOUND },
diagnostic.getChildren().get(0));
}
// The lower bound of a typed element must be less than or equal to the upper bound, unless the upper bound is -1, or -2.
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName("a");
eAttribute.setEType(EcorePackage.Literals.ESTRING);
eAttribute.setLowerBound(2);
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eAttribute);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_BOUNDS,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eAttribute, EcorePackage.Literals.ETYPED_ELEMENT__LOWER_BOUND, EcorePackage.Literals.ETYPED_ELEMENT__UPPER_BOUND },
diagnostic.getChildren().get(0));
}
// An attribute must have a type that's a data type.
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName("a");
eAttribute.setEType(EcorePackage.Literals.EOBJECT); // <-- Bad class type.
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eAttribute);
assertEquals(Diagnostic.ERROR, diagnostic.getSeverity());
assertEquals(2, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EObjectValidator.EOBJECT__EVERY_MULTIPCITY_CONFORMS,
EObjectValidator.DIAGNOSTIC_SOURCE,
new Object [] { eAttribute, EcorePackage.Literals.EATTRIBUTE__EATTRIBUTE_TYPE },
diagnostic.getChildren().get(0));
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_TYPE_CLASS_NOT_PERMITTED,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eAttribute.getEGenericType(), EcorePackage.Literals.EGENERIC_TYPE__ECLASSIFIER },
diagnostic.getChildren().get(1));
}
// A generic type used as the type of an attribute must not refer to a class.
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName("a");
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(EcorePackage.Literals.EOBJECT); // <-- Bad class type.
eAttribute.setEGenericType(eGenericType);
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eAttribute);
assertEquals(Diagnostic.ERROR, diagnostic.getSeverity());
assertEquals(2, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EObjectValidator.EOBJECT__EVERY_MULTIPCITY_CONFORMS,
EObjectValidator.DIAGNOSTIC_SOURCE,
new Object [] { eAttribute, EcorePackage.Literals.EATTRIBUTE__EATTRIBUTE_TYPE },
diagnostic.getChildren().get(0));
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_TYPE_CLASS_NOT_PERMITTED,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eGenericType, EcorePackage.Literals.EGENERIC_TYPE__ECLASSIFIER },
diagnostic.getChildren().get(1));
}
// A reference must have a type that's a class.
{
EReference eReference = EcoreFactory.eINSTANCE.createEReference();
eReference.setName("r");
eReference.setEType(EcorePackage.Literals.ESTRING);
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eReference);
assertEquals(2, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EObjectValidator.EOBJECT__EVERY_MULTIPCITY_CONFORMS,
EObjectValidator.DIAGNOSTIC_SOURCE,
new Object [] { eReference, EcorePackage.Literals.EREFERENCE__EREFERENCE_TYPE },
diagnostic.getChildren().get(0));
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_TYPE_DATA_TYPE_NOT_PERMITTED,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eReference.getEGenericType(), EcorePackage.Literals.EGENERIC_TYPE__ECLASSIFIER },
diagnostic.getChildren().get(1));
}
// A generic type used as the type of a reference must not refer to a data type.
{
EReference eReference = EcoreFactory.eINSTANCE.createEReference();
eReference.setName("r");
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(EcorePackage.Literals.EJAVA_OBJECT);
eReference.setEGenericType(eGenericType);
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eReference);
assertEquals(2, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EObjectValidator.EOBJECT__EVERY_MULTIPCITY_CONFORMS,
EObjectValidator.DIAGNOSTIC_SOURCE,
new Object [] { eReference, EcorePackage.Literals.EREFERENCE__EREFERENCE_TYPE },
diagnostic.getChildren().get(0));
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_TYPE_DATA_TYPE_NOT_PERMITTED,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eReference.getEGenericType(), EcorePackage.Literals.EGENERIC_TYPE__ECLASSIFIER },
diagnostic.getChildren().get(1));
}
// A reference with a valid key that's a feature of the reference's type.
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("_");
EAttribute a;
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName("a");
eAttribute.setEType(EcorePackage.Literals.ESTRING);
eClass.getEStructuralFeatures().add(eAttribute);
a = eAttribute;
}
{
EReference eReference = EcoreFactory.eINSTANCE.createEReference();
eReference.setName("r");
eReference.setEType(eClass);
eReference.getEKeys().add(a);
eClass.getEStructuralFeatures().add(eReference);
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eClass);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
}
// Reference with a key that isn't a feature of the type.
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("_");
EAttribute a;
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName("a");
eAttribute.setEType(EcorePackage.Literals.ESTRING);
eClass.getEStructuralFeatures().add(eAttribute);
a = eAttribute;
}
EReference r;
{
EReference eReference = EcoreFactory.eINSTANCE.createEReference();
eReference.setName("r");
eReference.setEType(EcorePackage.Literals.EOBJECT); // <-- Reference's type doesn't have the key attribute as a feature.
eReference.getEKeys().add(a);
eClass.getEStructuralFeatures().add(eReference);
r = eReference;
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eClass);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_KEYS,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { r, a, EcorePackage.Literals.EREFERENCE__EKEYS },
diagnostic.getChildren().get(0));
}
// A generic type can act as a wildcard only when used as the type argument of a generic type, not when used as the type of a type element.
{
EOperation eOperation = EcoreFactory.eINSTANCE.createEOperation();
eOperation.setName("_");
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eOperation.setEGenericType(eGenericType);
// eGenericType.setETypeParameter(...); // <-- Neither a type parameter
// eGenericType.setEClassifier(...); // <-- Nor a classifier.
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eOperation);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_TYPE_WILDCARD_NOT_PERMITTED,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eGenericType, EcorePackage.Literals.EGENERIC_TYPE__ECLASSIFIER, EcorePackage.Literals.EGENERIC_TYPE__ETYPE_PARAMETER },
diagnostic.getChildren().get(0));
}
// A generic type must not reference both a classifier and a type parameter.
{
ETypeParameter T;
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("_");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("T");
eClass.getETypeParameters().add(eTypeParameter);
T = eTypeParameter;
}
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("U");
eClass.getETypeParameters().add(eTypeParameter);
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setETypeParameter(T); // <-- Both a type parameter
eGenericType.setEClassifier(EcorePackage.Literals.EOBJECT); // <-- And a classifier.
eTypeParameter.getEBounds().add(eGenericType);
}
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eClass);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_TYPE_NO_TYPE_PARAMETER_AND_CLASSIFIER,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eClass.getETypeParameters().get(1).getEBounds().get(0), EcorePackage.Literals.EGENERIC_TYPE__ECLASSIFIER, EcorePackage.Literals.EGENERIC_TYPE__ETYPE_PARAMETER },
diagnostic.getChildren().get(0));
}
// A generic super type must refer to a class.
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("_");
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(EcorePackage.Literals.EJAVA_OBJECT); // <-- Bad reference to data type.
eClass.getEGenericSuperTypes().add(eGenericType);
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eClass);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_TYPE_CLASS_REQUIRED,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eClass.getEGenericSuperTypes().get(0), EcorePackage.Literals.EGENERIC_TYPE__ECLASSIFIER },
diagnostic.getChildren().get(0));
}
// No two generic super types may reference the same class.
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("_");
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(EcorePackage.Literals.EOBJECT); // <-- Both refer to EObject.
eClass.getEGenericSuperTypes().add(eGenericType);
}
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(EcorePackage.Literals.EOBJECT); // <-- Both refer to EObject.
eClass.getEGenericSuperTypes().add(eGenericType);
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eClass);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_SUPER_TYPES_DUPLICATE,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eClass, eClass.getEGenericSuperTypes().get(0), eClass.getEGenericSuperTypes().get(1), EcorePackage.Literals.ECLASS__EGENERIC_SUPER_TYPES },
diagnostic.getChildren().get(0));
}
// A generic type used as a type argument can be a wildcard.
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName("a");
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(EcorePackage.Literals.EJAVA_CLASS);
eAttribute.setEGenericType(eGenericType);
{
EGenericType eGenericTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.getETypeArguments().add(eGenericTypeArgument);
}
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eAttribute);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
}
// A generic type used as a valid wildcard can have a lower bound.
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName("a");
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(EcorePackage.Literals.EJAVA_CLASS);
eAttribute.setEGenericType(eGenericType);
{
EGenericType eGenericTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
{
EGenericType eGenericTypeLowerBound = EcoreFactory.eINSTANCE.createEGenericType();
eGenericTypeLowerBound.setEClassifier(EcorePackage.Literals.EOBJECT);
eGenericTypeArgument.setEUpperBound(eGenericTypeLowerBound);
}
eGenericType.getETypeArguments().add(eGenericTypeArgument);
}
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eAttribute);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
}
// A generic type used as a valid wildcard can have an upper bound.
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName("a");
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(EcorePackage.Literals.EJAVA_CLASS);
eAttribute.setEGenericType(eGenericType);
{
EGenericType eGenericTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
{
EGenericType eGenericTypeUpperBound = EcoreFactory.eINSTANCE.createEGenericType();
eGenericTypeUpperBound.setEClassifier(EcorePackage.Literals.EOBJECT);
eGenericTypeArgument.setEUpperBound(eGenericTypeUpperBound);
}
eGenericType.getETypeArguments().add(eGenericTypeArgument);
}
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eAttribute);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
}
// A generic type can't have both an upper and lower bound.
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName("a");
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(EcorePackage.Literals.EJAVA_CLASS);
eAttribute.setEGenericType(eGenericType);
{
EGenericType eGenericTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
{
EGenericType eGenericTypeLowerBound = EcoreFactory.eINSTANCE.createEGenericType();
eGenericTypeLowerBound.setEClassifier(EcorePackage.Literals.EOBJECT);
eGenericTypeArgument.setELowerBound(eGenericTypeLowerBound); // <-- A lower bound.
}
{
EGenericType eGenericTypeUpperBound = EcoreFactory.eINSTANCE.createEGenericType();
eGenericTypeUpperBound.setEClassifier(EcorePackage.Literals.EOBJECT);
eGenericTypeArgument.setEUpperBound(eGenericTypeUpperBound); // <-- And an upper bound.
}
eGenericType.getETypeArguments().add(eGenericTypeArgument);
}
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eAttribute);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_BOUNDS_NO_LOWER_AND_UPPER,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eAttribute.getEGenericType().getETypeArguments().get(0), EcorePackage.Literals.EGENERIC_TYPE__ELOWER_BOUND, EcorePackage.Literals.EGENERIC_TYPE__EUPPER_BOUND },
diagnostic.getChildren().get(0));
}
// A generic type can't have an upper bound except when used as a type argument.
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("_");
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(EcorePackage.Literals.EOBJECT);
{
EGenericType eGenericTypeUpperBound = EcoreFactory.eINSTANCE.createEGenericType();
eGenericTypeUpperBound.setEClassifier(EcorePackage.Literals.EOBJECT);
eGenericType.setEUpperBound(eGenericTypeUpperBound); // <-- Can't have bounds in this context.
}
eClass.getEGenericSuperTypes().add(eGenericType);
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eClass);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_BOUNDS_NOT_ALLOWED,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eClass.getEGenericSuperTypes().get(0), EcorePackage.Literals.EGENERIC_TYPE__EUPPER_BOUND },
diagnostic.getChildren().get(0));
}
// A generic type with bounds can't also refer to a type parameter or classifier
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName("a");
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(EcorePackage.Literals.EJAVA_CLASS);
eAttribute.setEGenericType(eGenericType);
{
EGenericType eGenericTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
eGenericTypeArgument.setEClassifier(EcorePackage.Literals.EJAVA_OBJECT); // <-- Can't have classifier with bounds.
{
EGenericType eGenericTypeUpperBound = EcoreFactory.eINSTANCE.createEGenericType();
eGenericTypeUpperBound.setEClassifier(EcorePackage.Literals.EOBJECT);
eGenericTypeArgument.setEUpperBound(eGenericTypeUpperBound); // <-- Can't have bounds with classifier.
}
eGenericType.getETypeArguments().add(eGenericTypeArgument);
}
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eAttribute);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_BOUNDS_NO_BOUNDS_WITH_TYPE_PARAMETER_OR_CLASSIFIER,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eAttribute.getEGenericType().getETypeArguments().get(0), EcorePackage.Literals.EGENERIC_TYPE__ECLASSIFIER },
diagnostic.getChildren().get(0));
}
// Generic type with arguments must have a classifier.
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
{
EGenericType eGenericTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
eGenericTypeArgument.setEClassifier(EcorePackage.Literals.EJAVA_OBJECT);
eGenericType.getETypeArguments().add(eGenericTypeArgument); // Can't have arguments because there is no classifier.
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eGenericType);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_ARGUMENTS_NONE_ALLOWED,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eGenericType, EcorePackage.Literals.EGENERIC_TYPE__ETYPE_ARGUMENTS },
diagnostic.getChildren().get(0));
}
// Generic type with classifier that specifies type parameters must have corresponding arguments,
// but it's only a warning, analogous to a raw type warning, to have no arguments when there are type parameters.
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(EcorePackage.Literals.EJAVA_CLASS);
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eGenericType);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.WARNING,
EcoreValidator.CONSISTENT_ARGUMENTS_NONE,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eGenericType, EcorePackage.Literals.EGENERIC_TYPE__ETYPE_ARGUMENTS },
diagnostic.getChildren().get(0));
}
// Generic type's classifier cannot specify a primitive type except as the generic type of a typed element.
{
EClass aClass = EcoreFactory.eINSTANCE.createEClass();
aClass.setName("AClass");
ETypeParameter e = EcoreFactory.eINSTANCE.createETypeParameter();
e.setName("E");
aClass.getETypeParameters().add(e);
EClass bClass = EcoreFactory.eINSTANCE.createEClass();
bClass.setName("BClass");
EGenericType superType = EcoreFactory.eINSTANCE.createEGenericType();
superType.setEClassifier(aClass);
EGenericType typeArgument = EcoreFactory.eINSTANCE.createEGenericType();
typeArgument.setEClassifier(EcorePackage.Literals.EINT);
superType.getETypeArguments().add(typeArgument);
bClass.getEGenericSuperTypes().add(superType);
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(bClass);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_TYPE_PRIMITIVE_TYPE_NOT_PERMITTED,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { typeArgument, EcorePackage.Literals.EGENERIC_TYPE__ECLASSIFIER },
diagnostic.getChildren().get(0));
}
// A generic type with classifier that specifies type parameters and that has arguments must have a matching number of them.
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(EcorePackage.Literals.EJAVA_CLASS);
{
EGenericType eGenericTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
eGenericTypeArgument.setEClassifier(EcorePackage.Literals.EJAVA_OBJECT);
eGenericType.getETypeArguments().add(eGenericTypeArgument);
}
{
EGenericType eGenericTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
eGenericTypeArgument.setEClassifier(EcorePackage.Literals.EJAVA_OBJECT);
eGenericType.getETypeArguments().add(eGenericTypeArgument); // <-- A second argument is not allowed.
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eGenericType);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_ARGUMENTS_INCORRECT_NUMBER,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eGenericType, EcorePackage.Literals.EGENERIC_TYPE__ETYPE_ARGUMENTS },
diagnostic.getChildren().get(0));
}
// Generic type must not reference an out of scope type parameter
{
ETypeParameter T;
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("_");
{
EOperation eOperation = EcoreFactory.eINSTANCE.createEOperation();
eOperation.setName("f");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("T");
eOperation.getETypeParameters().add(eTypeParameter);
T = eTypeParameter;
}
eClass.getEOperations().add(eOperation);
}
{
EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
eAttribute.setName("a");
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setETypeParameter(T);
eAttribute.setEGenericType(eGenericType);
}
eClass.getEStructuralFeatures().add(eAttribute);
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eClass);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_TYPE_TYPE_PARAMETER_NOT_IN_SCOPE,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eClass.getEStructuralFeatures().get(0).getEGenericType(), EcorePackage.Literals.EGENERIC_TYPE__ETYPE_PARAMETER },
diagnostic.getChildren().get(0));
}
// Generic type must not make a forward reference to a type parameter
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("_");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("T");
eClass.getETypeParameters().add(eTypeParameter);
{
EGenericType eBound = EcoreFactory.eINSTANCE.createEGenericType();
eBound.setETypeParameter(eTypeParameter);
eTypeParameter.getEBounds().add(eBound);
}
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eClass);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_TYPE_TYPE_PARAMETER_NOT_IN_SCOPE,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { eClass.getETypeParameters().get(0).getEBounds().get(0), EcorePackage.Literals.EGENERIC_TYPE__ETYPE_PARAMETER },
diagnostic.getChildren().get(0));
}
// Type parameter can be used as the type argument of the
// bound
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("_");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("T");
eClass.getETypeParameters().add(eTypeParameter);
{
EGenericType eBound = EcoreFactory.eINSTANCE.createEGenericType();
eBound.setEClassifier(eClass);
eTypeParameter.getEBounds().add(eBound);
EGenericType typeArgument = EcoreFactory.eINSTANCE.createEGenericType();
typeArgument.setETypeParameter(eTypeParameter);
eBound.getETypeArguments().add(typeArgument);
}
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eClass);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
}
// A generic super type can validly use type arguments.
{
EClass A;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("A");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("T");
eClass.getETypeParameters().add(eTypeParameter);
}
A = eClass;
}
EClass B;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("B");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("T");
eClass.getETypeParameters().add(eTypeParameter);
}
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(A);
eClass.getEGenericSuperTypes().add(eGenericType);
{
EGenericType eGenericTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
eGenericTypeArgument.setETypeParameter(eClass.getETypeParameters().get(0));
eGenericType.getETypeArguments().add(eGenericTypeArgument);
}
}
B = eClass;
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(B);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
}
// A generic super type must not have wildcard type arguments.
{
EClass A;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("A");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("T");
eClass.getETypeParameters().add(eTypeParameter);
}
A = eClass;
}
EClass B;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("B");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("T");
eClass.getETypeParameters().add(eTypeParameter);
}
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(A);
eClass.getEGenericSuperTypes().add(eGenericType);
{
EGenericType eGenericTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.getETypeArguments().add(eGenericTypeArgument);
}
}
B = eClass;
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(B);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_TYPE_WILDCARD_NOT_PERMITTED,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { B.getEGenericSuperTypes().get(0).getETypeArguments().get(0), EcorePackage.Literals.EGENERIC_TYPE__ECLASSIFIER, EcorePackage.Literals.EGENERIC_TYPE__ETYPE_PARAMETER },
diagnostic.getChildren().get(0));
}
// Generic super types can pass template parameters in complex ways with redundant diamond inheritance.
{
EClass A;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("A");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("T");
eClass.getETypeParameters().add(eTypeParameter);
}
A = eClass;
}
EClass B;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("B");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("T");
eClass.getETypeParameters().add(eTypeParameter);
}
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(A);
eClass.getEGenericSuperTypes().add(eGenericType);
{
EGenericType eGenericTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
eGenericTypeArgument.setETypeParameter(eClass.getETypeParameters().get(0));
eGenericType.getETypeArguments().add(eGenericTypeArgument);
}
}
B = eClass;
}
EClass C;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("C");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("T");
eClass.getETypeParameters().add(eTypeParameter);
}
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(A);
eClass.getEGenericSuperTypes().add(eGenericType);
{
EGenericType eGenericTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
eGenericTypeArgument.setETypeParameter(eClass.getETypeParameters().get(0));
eGenericType.getETypeArguments().add(eGenericTypeArgument);
}
}
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(B);
eClass.getEGenericSuperTypes().add(eGenericType);
{
EGenericType eGenericTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
eGenericTypeArgument.setETypeParameter(eClass.getETypeParameters().get(0));
eGenericType.getETypeArguments().add(eGenericTypeArgument);
}
}
C = eClass;
}
assertEquals(2, C.getEAllGenericSuperTypes().size());
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(C);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
}
// Generic super types can pass instantiate template parameters in complex ways with redundant diamond inheritance.
{
EClass A;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("A");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("T");
eClass.getETypeParameters().add(eTypeParameter);
}
A = eClass;
}
EClass B;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("B");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("T");
eClass.getETypeParameters().add(eTypeParameter);
}
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(A);
eClass.getEGenericSuperTypes().add(eGenericType);
{
EGenericType eGenericTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
eGenericTypeArgument.setETypeParameter(eClass.getETypeParameters().get(0));
eGenericType.getETypeArguments().add(eGenericTypeArgument);
}
}
B = eClass;
}
EClass C;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("C");
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(A);
eClass.getEGenericSuperTypes().add(eGenericType);
{
EGenericType eGenericTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
eGenericTypeArgument.setEClassifier(EcorePackage.Literals.ESTRING); // <-- Use EString for A here.
eGenericType.getETypeArguments().add(eGenericTypeArgument);
}
}
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(B);
eClass.getEGenericSuperTypes().add(eGenericType);
{
EGenericType eGenericTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
eGenericTypeArgument.setEClassifier(EcorePackage.Literals.ESTRING); // <-- Both use EString for B and hence indirectly for A.
eGenericType.getETypeArguments().add(eGenericTypeArgument);
}
}
C = eClass;
}
assertEquals(2, C.getEAllGenericSuperTypes().size());
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(C);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
}
// Generic super types can pass instantiate template parameters in complex ways with redundant diamond inheritance.
{
EClass A;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("A");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("T");
eClass.getETypeParameters().add(eTypeParameter);
}
A = eClass;
}
EClass B;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("B");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("T");
eClass.getETypeParameters().add(eTypeParameter);
}
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(A);
eClass.getEGenericSuperTypes().add(eGenericType);
{
EGenericType eGenericTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
eGenericTypeArgument.setETypeParameter(eClass.getETypeParameters().get(0));
eGenericType.getETypeArguments().add(eGenericTypeArgument);
}
}
B = eClass;
}
EClass C;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("C");
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(A);
eClass.getEGenericSuperTypes().add(eGenericType);
{
EGenericType eGenericTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
eGenericTypeArgument.setEClassifier(EcorePackage.Literals.ESTRING); // <-- Use EString for A here.
eGenericType.getETypeArguments().add(eGenericTypeArgument);
}
}
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(B);
eClass.getEGenericSuperTypes().add(eGenericType);
{
EGenericType eGenericTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
eGenericTypeArgument.setEClassifier(EcorePackage.Literals.EINTEGER_OBJECT); // <-- Both use EInteger for B and hence indirectly for A.
eGenericType.getETypeArguments().add(eGenericTypeArgument);
}
}
C = eClass;
}
assertEquals(3, C.getEAllGenericSuperTypes().size());
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(C);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_SUPER_TYPES_CONFLICT,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object [] { C, C.getEAllGenericSuperTypes().get(1), C.getEAllGenericSuperTypes().get(0), EcorePackage.Literals.ECLASS__EALL_GENERIC_SUPER_TYPES },
diagnostic.getChildren().get(0));
}
LOOP:
for (int i = 0; i < 100; ++i)
{
EPackage ePackage = EcoreFactory.eINSTANCE.createEPackage();
ePackage.setName("_");
ePackage.setNsURI("_");
ePackage.setNsPrefix("");
// interface X {}
//
EClass X;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("X");
ePackage.getEClassifiers().add(eClass);
X = eClass;
}
// interface Y extends X {}
//
EClass Y;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("Y");
eClass.getESuperTypes().add(X);
ePackage.getEClassifiers().add(eClass);
Y = eClass;
}
// interface Container<E> {}
//
EClass Container;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("Container");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("E");
eClass.getETypeParameters().add(eTypeParameter);
}
ePackage.getEClassifiers().add(eClass);
Container = eClass;
}
// interface A<T extends Container<?>> {}
//
EClass A;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("A");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("T");
eClass.getETypeParameters().add(eTypeParameter);
{
EGenericType eBound = EcoreFactory.eINSTANCE.createEGenericType();
eBound.setEClassifier(Container);
{
EGenericType eTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
if (i == 2 || i == 3)
{
eTypeArgument.setEClassifier(X); // <-- Container<?> or Container<X>
}
eBound.getETypeArguments().add(eTypeArgument);
}
eTypeParameter.getEBounds().add(eBound);
}
}
ePackage.getEClassifiers().add(eClass);
A = eClass;
}
// interface B<T extends Container<EString>> extends A<T> {}
//
EClass B;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("B");
ETypeParameter T;
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("T");
// <-- If we don't set a bound, that satisfies A's bound, which requires a Container,
// then it won't be valid to pass T as the argument to A<T>.
//
if (i != 1)
{
EGenericType eBound = EcoreFactory.eINSTANCE.createEGenericType();
eBound.setEClassifier(Container);
{
EGenericType eTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
if (i == 2)
{
eTypeArgument.setEClassifier(X); // <-- Container<X> is fine
}
else if (i == 3)
{
eTypeArgument.setEClassifier(Y); // <-- Container<Y> is an error
}
else
{
eTypeArgument.setEClassifier(EcorePackage.Literals.ESTRING); // <-- Container<EString> is fine.
}
eBound.getETypeArguments().add(eTypeArgument);
}
eTypeParameter.getEBounds().add(eBound);
}
eClass.getETypeParameters().add(eTypeParameter);
T = eTypeParameter;
}
{
EGenericType eGenericSuperType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericSuperType.setEClassifier(A);
{
EGenericType eTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
eTypeArgument.setETypeParameter(T);
eGenericSuperType.getETypeArguments().add(eTypeArgument);
}
eClass.getEGenericSuperTypes().add(eGenericSuperType);
}
ePackage.getEClassifiers().add(eClass);
B = eClass;
}
switch (i)
{
case 0:
{
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
break;
}
case 1:
{
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_ARGUMENTS_INVALID_SUBSTITUTION,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object []
{
B.getEGenericSuperTypes().get(0),
B.getEGenericSuperTypes().get(0).getETypeArguments().get(0),
A.getETypeParameters().get(0),
EcorePackage.Literals.EGENERIC_TYPE__ETYPE_ARGUMENTS
},
diagnostic.getChildren().get(0));
break;
}
case 2:
{
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
break;
}
case 3:
{
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_ARGUMENTS_INVALID_SUBSTITUTION,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object []
{
B.getEGenericSuperTypes().get(0),
B.getEGenericSuperTypes().get(0).getETypeArguments().get(0),
A.getETypeParameters().get(0),
EcorePackage.Literals.EGENERIC_TYPE__ETYPE_ARGUMENTS
},
diagnostic.getChildren().get(0));
break;
}
default:
{
break LOOP;
}
}
}
}
interface X
{
//
}
interface Y extends X
{
//
}
interface Container<E>
{
//
}
interface DerivedContainer<E> extends Container<E>
{
//
}
interface Holder<E, F extends E, H extends Container<E>>
{
<E1, F1 extends E1, G1 extends Container<E1>> void foo();
}
@Test
public void testMatching()
{
LOOP:
for (int i = 0; i < 100; ++i)
{
EPackage ePackage = EcoreFactory.eINSTANCE.createEPackage();
ePackage.setName("_");
ePackage.setNsURI("_");
ePackage.setNsPrefix("");
// interface X {}
//
EClass eClassX;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("X");
ePackage.getEClassifiers().add(eClass);
eClassX = eClass;
}
// interface Y extends X {}
//
// EClass eClassY;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("Y");
eClass.getESuperTypes().add(eClassX);
ePackage.getEClassifiers().add(eClass);
// eClassY = eClass;
}
// interface Container<E> {}
//
EClass eClassContainer;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("Container");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("E");
eClass.getETypeParameters().add(eTypeParameter);
}
ePackage.getEClassifiers().add(eClass);
eClassContainer = eClass;
}
// interface DerivedContainer<E> extends Container<E> {}
//
// EClass eClassDerivedContainer;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("DerivedContainer");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("E");
eClass.getETypeParameters().add(eTypeParameter);
}
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(eClassContainer);
{
EGenericType eTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
eTypeArgument.setETypeParameter(eClass.getETypeParameters().get(0));
eGenericType.getETypeArguments().add(eTypeArgument);
}
eClass.getEGenericSuperTypes().add(eGenericType);
}
ePackage.getEClassifiers().add(eClass);
// eClassDerivedContainer = eClass;
}
// interface Holder<E, F extends E, G extends Container<E>>
// {
// <E1, F1 extends E1, G1 extends Container<E1>> void foo();
// }
//
EClass eClassHolder;
EOperation eOperationFoo;
{
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("Holder");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("E");
eClass.getETypeParameters().add(eTypeParameter);
}
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("F");
{
EGenericType eBound = EcoreFactory.eINSTANCE.createEGenericType();
eBound.setETypeParameter(eClass.getETypeParameters().get(0));
eTypeParameter.getEBounds().add(eBound);
}
eClass.getETypeParameters().add(eTypeParameter);
}
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("G");
{
EGenericType eBound = EcoreFactory.eINSTANCE.createEGenericType();
eBound.setEClassifier(eClassContainer);
if (i <= 5) // Container<E> or Container<? extends E> or <Container<? super E>>
{
EGenericType eTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
eTypeArgument.setETypeParameter(eClass.getETypeParameters().get(0));
eBound.getETypeArguments().add(eTypeArgument);
}
else
{
EGenericType eTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
if (i < 8)
{
EGenericType eUpperBound = EcoreFactory.eINSTANCE.createEGenericType();
eUpperBound.setETypeParameter(eClass.getETypeParameters().get(0));
eTypeArgument.setEUpperBound(eUpperBound);
}
else
{
EGenericType eLowerBound = EcoreFactory.eINSTANCE.createEGenericType();
eLowerBound.setETypeParameter(eClass.getETypeParameters().get(0));
eTypeArgument.setELowerBound(eLowerBound);
}
eBound.getETypeArguments().add(eTypeArgument);
}
eTypeParameter.getEBounds().add(eBound);
}
eClass.getETypeParameters().add(eTypeParameter);
}
ePackage.getEClassifiers().add(eClass);
eClassHolder = eClass;
{
EOperation eOperation = EcoreFactory.eINSTANCE.createEOperation();
eOperation.setName("foo");
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("E1");
eOperation.getETypeParameters().add(eTypeParameter);
}
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("F1");
{
EGenericType eBound = EcoreFactory.eINSTANCE.createEGenericType();
eBound.setETypeParameter(eOperation.getETypeParameters().get(0));
eTypeParameter.getEBounds().add(eBound);
}
eOperation.getETypeParameters().add(eTypeParameter);
}
{
ETypeParameter eTypeParameter = EcoreFactory.eINSTANCE.createETypeParameter();
eTypeParameter.setName("G1");
{
EGenericType eBound = EcoreFactory.eINSTANCE.createEGenericType();
eBound.setEClassifier(eClassContainer);
{
EGenericType eTypeArgument = EcoreFactory.eINSTANCE.createEGenericType();
eTypeArgument.setETypeParameter(eOperation.getETypeParameters().get(0));
eBound.getETypeArguments().add(eTypeArgument);
}
eTypeParameter.getEBounds().add(eBound);
}
eOperation.getETypeParameters().add(eTypeParameter);
}
eClass.getEOperations().add(eOperation);
eOperationFoo = eOperation;
}
}
switch (i)
{
case 0:
{
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
break;
}
case 1:
{
EParameter eParameter = EcoreFactory.eINSTANCE.createEParameter();
eParameter.setName("x");
eOperationFoo.getEParameters().add(eParameter);
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(eClassHolder);
{
EGenericType eTypeParameter = EcoreFactory.eINSTANCE.createEGenericType();
eTypeParameter.setETypeParameter(eOperationFoo.getETypeParameters().get(0));
eGenericType.getETypeArguments().add(eTypeParameter);
}
{
EGenericType eTypeParameter = EcoreFactory.eINSTANCE.createEGenericType();
eTypeParameter.setETypeParameter(eOperationFoo.getETypeParameters().get(1));
eGenericType.getETypeArguments().add(eTypeParameter);
}
{
EGenericType eTypeParameter = EcoreFactory.eINSTANCE.createEGenericType();
eTypeParameter.setETypeParameter(eOperationFoo.getETypeParameters().get(2));
eGenericType.getETypeArguments().add(eTypeParameter);
}
eParameter.setEGenericType(eGenericType);
}
class HolderCase1<E, F extends E, H extends Container<E>>
{
@SuppressWarnings("unused")
<E1, F1 extends E1, G1 extends Container<E1>> void foo(HolderCase1<E1, F1, G1> x)
{
this.foo(x);
}
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
break;
}
case 2:
{
EParameter eParameter = EcoreFactory.eINSTANCE.createEParameter();
eParameter.setName("x");
eOperationFoo.getEParameters().add(eParameter);
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(eClassHolder);
{
EGenericType eTypeParameter = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.getETypeArguments().add(eTypeParameter);
}
{
EGenericType eTypeParameter = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.getETypeArguments().add(eTypeParameter);
}
{
EGenericType eTypeParameter = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.getETypeArguments().add(eTypeParameter);
}
eParameter.setEGenericType(eGenericType);
}
class HolderCase2<E, F extends E, H extends Container<E>>
{
@SuppressWarnings("unused")
<E1, F1 extends E1, G1 extends Container<E1>> void foo(HolderCase2<?, ?, ?> x)
{
this.foo(x);
}
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
break;
}
case 3:
{
EParameter eParameter = EcoreFactory.eINSTANCE.createEParameter();
eParameter.setName("x");
eOperationFoo.getEParameters().add(eParameter);
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(eClassHolder);
{
EGenericType eTypeParameter = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.getETypeArguments().add(eTypeParameter);
}
{
EGenericType eTypeParameter = EcoreFactory.eINSTANCE.createEGenericType();
{
EGenericType eUpperBound = EcoreFactory.eINSTANCE.createEGenericType();
eUpperBound.setETypeParameter(eOperationFoo.getETypeParameters().get(1)); // <-- ? extends E1
eTypeParameter.setEUpperBound(eUpperBound);
}
eGenericType.getETypeArguments().add(eTypeParameter);
}
{
EGenericType eTypeParameter = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.getETypeArguments().add(eTypeParameter);
}
eParameter.setEGenericType(eGenericType);
}
@SuppressWarnings("unused")
class HolderCase3<E, F extends E, H extends Container<E>>
{
<E1, F1 extends E1, G1 extends Container<E1>> void foo(/* --> HolderCase3<?, ? extends E1, ?> x <-- */)
{
this.foo(/*x*/);
}
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_ARGUMENTS_INVALID_SUBSTITUTION,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object []
{
eOperationFoo.getEParameters().get(0).getEGenericType(),
eOperationFoo.getEParameters().get(0).getEGenericType().getETypeArguments().get(1),
eClassHolder.getETypeParameters().get(1),
EcorePackage.Literals.EGENERIC_TYPE__ETYPE_ARGUMENTS
},
diagnostic.getChildren().get(0));
break;
}
case 4:
{
EParameter eParameter = EcoreFactory.eINSTANCE.createEParameter();
eParameter.setName("x");
eOperationFoo.getEParameters().add(eParameter);
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(eClassHolder);
{
EGenericType eTypeParameter = EcoreFactory.eINSTANCE.createEGenericType();
eTypeParameter.setETypeParameter(eOperationFoo.getETypeParameters().get(0));
eGenericType.getETypeArguments().add(eTypeParameter);
}
{
EGenericType eTypeParameter = EcoreFactory.eINSTANCE.createEGenericType();
eTypeParameter.setETypeParameter(eOperationFoo.getETypeParameters().get(1));
eGenericType.getETypeArguments().add(eTypeParameter);
}
{
EGenericType eTypeParameter = EcoreFactory.eINSTANCE.createEGenericType();
eTypeParameter.setEClassifier(eClassContainer); // <-- Container
eGenericType.getETypeArguments().add(eTypeParameter);
}
eParameter.setEGenericType(eGenericType);
}
@SuppressWarnings("unused")
class HolderCase4<E, F extends E, H extends Container<E>>
{
<E1, F1 extends E1, G1 extends Container<E1>> void foo(/* --> HolderCase4<E1, F1, Container> x <-- */)
{
this.foo(/*x*/);
}
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(2, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_ARGUMENTS_INVALID_SUBSTITUTION,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object []
{
eOperationFoo.getEParameters().get(0).getEGenericType(),
eOperationFoo.getEParameters().get(0).getEGenericType().getETypeArguments().get(2),
eClassHolder.getETypeParameters().get(2),
EcorePackage.Literals.EGENERIC_TYPE__ETYPE_ARGUMENTS
},
diagnostic.getChildren().get(0));
assertDiagnostic
(Diagnostic.WARNING,
EcoreValidator.CONSISTENT_ARGUMENTS_NONE,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object []
{
eOperationFoo.getEParameters().get(0).getEGenericType().getETypeArguments().get(2), EcorePackage.Literals.EGENERIC_TYPE__ETYPE_ARGUMENTS
},
diagnostic.getChildren().get(1));
break;
}
case 5:
{
EParameter eParameter = EcoreFactory.eINSTANCE.createEParameter();
eParameter.setName("x");
eOperationFoo.getEParameters().add(eParameter);
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(eClassHolder);
{
EGenericType eTypeParameter = EcoreFactory.eINSTANCE.createEGenericType();
eTypeParameter.setETypeParameter(eOperationFoo.getETypeParameters().get(0));
eGenericType.getETypeArguments().add(eTypeParameter);
}
{
EGenericType eTypeParameter = EcoreFactory.eINSTANCE.createEGenericType();
eTypeParameter.setETypeParameter(eOperationFoo.getETypeParameters().get(1));
eGenericType.getETypeArguments().add(eTypeParameter);
}
{
EGenericType eTypeParameter = EcoreFactory.eINSTANCE.createEGenericType();
eTypeParameter.setEClassifier(eClassContainer); // <-- Container
{
EGenericType eTypeParameterU1 = EcoreFactory.eINSTANCE.createEGenericType();
eTypeParameterU1.setETypeParameter(eOperationFoo.getETypeParameters().get(1)); // <-- F1
eTypeParameter.getETypeArguments().add(eTypeParameterU1);
}
eGenericType.getETypeArguments().add(eTypeParameter);
}
eParameter.setEGenericType(eGenericType);
}
@SuppressWarnings("unused")
class HolderCase5<E, F extends E, H extends Container<E>>
{
<E1, F1 extends E1, G1 extends Container<E1>> void foo(/* --> HolderCase5<E1, F1, Container<F1>> x <-- */)
{
this.foo(/*x*/);
}
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_ARGUMENTS_INVALID_SUBSTITUTION,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object []
{
eOperationFoo.getEParameters().get(0).getEGenericType(),
eOperationFoo.getEParameters().get(0).getEGenericType().getETypeArguments().get(2),
eClassHolder.getETypeParameters().get(2),
EcorePackage.Literals.EGENERIC_TYPE__ETYPE_ARGUMENTS
},
diagnostic.getChildren().get(0));
break;
}
case 6:
{
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
break;
}
case 7:
{
EParameter eParameter = EcoreFactory.eINSTANCE.createEParameter();
eParameter.setName("x");
eOperationFoo.getEParameters().add(eParameter);
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(eClassHolder);
{
EGenericType eTypeParameter = EcoreFactory.eINSTANCE.createEGenericType();
eTypeParameter.setETypeParameter(eOperationFoo.getETypeParameters().get(0));
eGenericType.getETypeArguments().add(eTypeParameter);
}
{
EGenericType eTypeParameter = EcoreFactory.eINSTANCE.createEGenericType();
eTypeParameter.setETypeParameter(eOperationFoo.getETypeParameters().get(1));
eGenericType.getETypeArguments().add(eTypeParameter);
}
{
EGenericType eTypeParameter = EcoreFactory.eINSTANCE.createEGenericType();
eTypeParameter.setEClassifier(eClassContainer); // <-- Container
{
EGenericType eTypeParameterU1 = EcoreFactory.eINSTANCE.createEGenericType();
eTypeParameterU1.setETypeParameter(eOperationFoo.getETypeParameters().get(1)); // <-- F1
eTypeParameter.getETypeArguments().add(eTypeParameterU1);
}
eGenericType.getETypeArguments().add(eTypeParameter);
}
eParameter.setEGenericType(eGenericType);
}
class HolderCase7<E, F extends E, H extends Container<? extends E>>
{
@SuppressWarnings("unused")
<E1, F1 extends E1, G1 extends Container<E1>> void foo(HolderCase7<E1, F1, Container<F1>> x)
{
this.foo(x);
}
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(Diagnostic.OK, diagnostic.getSeverity());
/*
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_ARGUMENTS_INVALID_SUBSTITUTION,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object []
{
eOperationFoo.getEParameters().get(0).getEGenericType(),
eOperationFoo.getEParameters().get(0).getEGenericType().getETypeArguments().get(2),
eClassHolder.getETypeParameters().get(2)
},
diagnostic.getChildren().get(0));
*/
break;
}
case 8:
{
EParameter eParameter = EcoreFactory.eINSTANCE.createEParameter();
eParameter.setName("x");
eOperationFoo.getEParameters().add(eParameter);
{
EGenericType eGenericType = EcoreFactory.eINSTANCE.createEGenericType();
eGenericType.setEClassifier(eClassHolder);
{
EGenericType eTypeParameter = EcoreFactory.eINSTANCE.createEGenericType();
eTypeParameter.setETypeParameter(eOperationFoo.getETypeParameters().get(0));
eGenericType.getETypeArguments().add(eTypeParameter);
}
{
EGenericType eTypeParameter = EcoreFactory.eINSTANCE.createEGenericType();
eTypeParameter.setETypeParameter(eOperationFoo.getETypeParameters().get(1));
eGenericType.getETypeArguments().add(eTypeParameter);
}
{
EGenericType eTypeParameter = EcoreFactory.eINSTANCE.createEGenericType();
eTypeParameter.setEClassifier(eClassContainer); // <-- Container
{
EGenericType eTypeParameterU1 = EcoreFactory.eINSTANCE.createEGenericType();
eTypeParameterU1.setETypeParameter(eOperationFoo.getETypeParameters().get(1)); // <-- F1
eTypeParameter.getETypeArguments().add(eTypeParameterU1);
}
eGenericType.getETypeArguments().add(eTypeParameter);
}
eParameter.setEGenericType(eGenericType);
}
@SuppressWarnings("unused")
class HolderCase8<E, F extends E, H extends Container<? super E>>
{
<E1, F1 extends E1, G1 extends Container<E1>> void foo(/* --> HolderCase8<E1, F1, Container<F1>> x <--*/)
{
this.foo(/*x*/);
}
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
assertEquals(1, diagnostic.getChildren().size());
assertDiagnostic
(Diagnostic.ERROR,
EcoreValidator.CONSISTENT_ARGUMENTS_INVALID_SUBSTITUTION,
EcoreValidator.DIAGNOSTIC_SOURCE,
new Object []
{
eOperationFoo.getEParameters().get(0).getEGenericType(),
eOperationFoo.getEParameters().get(0).getEGenericType().getETypeArguments().get(2),
eClassHolder.getETypeParameters().get(2),
EcorePackage.Literals.EGENERIC_TYPE__ETYPE_ARGUMENTS
},
diagnostic.getChildren().get(0));
break;
}
default:
{
break LOOP;
}
}
}
}
public void validateAllRegisteredModels()
{
// Validate all registered models.
//
if (!"false".equals(System.getProperty(EcoreValidationTest.class.getName() + ".validateAllRegisteredModels", "false")))
{
for (String nsURI : new HashSet<String>(EPackage.Registry.INSTANCE.keySet()))
{
EPackage ePackage = null;
try
{
ePackage = EPackage.Registry.INSTANCE.getEPackage(nsURI);
}
catch (Throwable exception)
{
// Ignore
}
if (ePackage != null)
{
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ePackage);
System.err.println("Validating " + nsURI);
for (Diagnostic child : diagnostic.getChildren())
{
switch (child.getSeverity())
{
case Diagnostic.ERROR:
{
System.err.print("error : ");
break;
}
case Diagnostic.WARNING:
{
System.err.print("warning: ");
break;
}
default:
{
System.err.print("other : ");
break;
}
}
System.err.println(child.getMessage());
}
}
}
}
}
public void assertDiagnostic(int severity, int code, String source, Object [] data, Diagnostic diagnostic)
{
if (SYSOUT) System.out.println(diagnostic.getMessage());
assertEquals(severity, diagnostic.getSeverity());
assertEquals(code, diagnostic.getCode());
assertEquals(source, diagnostic.getSource());
assertEquals(Arrays.asList(data), diagnostic.getData());
}
}